#pragma once

#include <immintrin.h>
#include <jlib/jlib.h>

USE_JLIB_NS


inline f64v4 v2dp (f64v4 x1, f64v4 y1, f64v4 x2, f64v4 y2) noexcept {
  auto x1x2 = _mm256_mul_pd(x1, x2);
  auto y1y2 = _mm256_mul_pd(y1, y2);
  return _mm256_add_pd(x1x2, y1y2);
}


inline f64v4 v2cp (f64v4 x1, f64v4 y1, f64v4 x2, f64v4 y2) noexcept {
  auto x1y2 = _mm256_mul_pd(x1, y2);
  auto x2y1 = _mm256_mul_pd(x2, y1);
  return _mm256_sub_pd(x1y2, x2y1);
}


inline void log_s4 (const std::string &name, f32v4 value) noexcept {
  log_i("%s: [ %f | %f | %f | %f ]", name.c_str(), value[0], value[1], value[2], value[3]);
}


inline void log_i4 (const std::string &name, s32v4 value) noexcept {
  log_i("%s: [ %d | %d | %d | %d ]", name.c_str(), value[0], value[1], value[2], value[3]);
}


inline void log_d4 (const std::string &name, f64v4 value) noexcept {
  log_i("%s: [ %lf | %lf | %lf | %lf ]", name.c_str(), value[0], value[1], value[2], value[3]);
}


inline void log_l4 (const std::string &name, s64v4 value) noexcept {
  log_i("%s: [ %lld | %lld | %lld | %lld ]", name.c_str(), value[0], value[1], value[2], value[3]);
}